package cn.bugstack.springframework.beans.factory.config;

import cn.bugstack.springframework.beans.BeansException;
import cn.bugstack.springframework.beans.PropertyValues;

/**
 * 为什么需要从BeanPostProcessor 接口中派生出InstantiationAwareBeanPostProcessor 接口？
 *
 * `BeanPostProcessor` 接口是 Spring 框架中的一个核心接口，它允许用户在 Spring 容器中的 bean 初始化前后添加自定义逻辑。
 * `BeanPostProcessor` 提供了两个方法：`postProcessBeforeInitialization` 和 `postProcessAfterInitialization`，分别用于在 bean 的初始化之前和之后进行操作。
 * 尽管 `BeanPostProcessor` 提供了在 bean 初始化阶段的扩展点，但它并没有提供在 bean 实例化阶段的直接干预手段。
 * 在实际应用中，有时需要在 bean 实例化之前进行一些处理，例如：
 * - 在创建 bean 实例之前创建一个代理对象。
 * - 根据某些条件决定是否跳过 bean 的创建。
 * - 对 bean 的类进行动态修改。
 * 为了满足这些需求，Spring 框架设计了 `InstantiationAwareBeanPostProcessor` 接口，它扩展了 `BeanPostProcessor` 接口，
 * 并添加了三个新方法，允许在 bean 实例化前后以及属性值设置前后进行操作。这样，开发者就有机会在 bean 的生命周期中更早的阶段插入自定义逻辑。
 * 通过派生出 `InstantiationAwareBeanPostProcessor`，Spring 提供了一个更细粒度的控制机制，使得框架的使用者能够实现更高级的自定义功能，
 * 而不仅仅是初始化前后的处理。这种设计体现了 Spring 框架的扩展性和灵活性，使得它能够适应各种不同的使用场景和需求。
 */

public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {

    /**
     *  在目标 bean 实例化之前执行。这个方法可以返回一个代理对象，用于替代原始的目标 bean 实例。
     *  如果返回了一个非空对象，Spring 容器会使用这个代理对象而不是原始的 bean 实例。
     *  这允许在 bean 实例化之前进行自定义处理，例如创建一个代理对象来包装原始 bean。
     */
    Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException;



    /**
     * 在对象实例化后进行后处理。
     * 此方法允许对新实例化的bean进行额外的处理，比如注入一些额外的属性或者执行一些初始化逻辑。
     *
     * @param bean 新实例化的对象。
     * @param beanName 对象在Spring容器中的名称。
     * @return 如果处理成功返回true，如果处理失败可以返回false。
     * @throws BeansException 如果在处理过程中遇到错误。
     */
    boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException;
    /**
     * Post-process the given property values before the factory applies them
     * to the given bean. Allows for checking whether all dependencies have been
     * satisfied, for example based on a "Required" annotation on bean property setters.
     *
     * 在 Bean 对象实例化完成后，设置属性操作之前执行此方法
     *
     * @param pvs
     * @param bean
     * @param beanName
     * @return
     * @throws BeansException
     */
    PropertyValues postProcessPropertyValues(PropertyValues pvs, Object bean, String beanName) throws BeansException;

}
